#include "../include/BaseLib.hpp"

namespace BaseLib 
{
	int create_and_bind_socket()
	{
		int ret, sockfd;
		sockaddr_in address;
		memset(&address, 0, sizeof(address));
		address.sin_family = AF_INET;
		address.sin_port = htons(SERVER_PORT);
		inet_pton(AF_INET, SERVER_ADDRESS, &address.sin_addr);
		sockfd = socket(AF_INET, SOCK_STREAM, 0);
		ERROR_FUNC_PRINT(sockfd < 0, "socket");
		printf("create server socket success!\n");
		set_noblocking(sockfd);
		ret = bind(sockfd, (sockaddr*)&address, sizeof(address));
		ERROR_FUNC_PRINT(ret < 0, "bind");
		printf("bind server socket success\n");
		return sockfd;
	}

	int set_noblocking(int sockfd) {
		int flags, ret;
		flags = fcntl(sockfd, F_GETFL, 0);
		ERROR_FUNC_PRINT(ret == -1, "fcntl");
		flags |= O_NONBLOCK;
		ret = fcntl(sockfd, F_SETFL, flags);
		ERROR_FUNC_PRINT(ret == -1, "fcntl");
		return flags;
	}

	int add_epoll(int epollfd,int fd)
	{
		epoll_event event;
		event.data.fd = fd;
		event.events = EPOLLIN | EPOLLET;
		int ret = epoll_ctl(epollfd,EPOLL_CTL_ADD,fd,&event);
		if(ret < 0) perror("epoll_ctl");
		set_noblocking(fd);
		return ret;
	}

	int broadcase_message(int fd, std::map<int,ClientData> client_list, char* buf, int size)
	{
		int ret = -1;
		if (client_list.size() > 1)
		{
			for (const auto& iter : client_list)
			{
				if (iter.first != fd) {
					ret = send(iter.first, buf, size, 0);
					ERROR_FUNC_PRINT(ret < 0, "send");
				}
			}
		}
		else
		{
			char tempBuf[BUF_SIZE] = { 0 };
			sprintf(tempBuf, "This no people in server,maybe a ghost want to send this message...[%s]", buf);
			ret = send(fd, tempBuf, strlen(tempBuf), 0);
			ERROR_FUNC_PRINT(ret < 0, "send");
		}
		return 0;
	}

	int ask_server_for_state(const char* str, int fd, const char* name,ClientData& client)
	{
		cJSON* cjson = cJSON_Parse(str);
		int result = 0;
		if (cjson == NULL)
		{
			printf("parse json error...");
			return -1;
		}
		auto User = cJSON_GetObjectItem(cjson, "User");
		if(User != NULL)
		{
			auto data = cJSON_GetObjectItem(User,name);
			if(data != NULL)
			{
				char* name = cJSON_GetObjectItem(data,"ClientName")->valuestring;
				int state = cJSON_GetObjectItem(data,"ClientState")->valueint;
				client.name = (char*)malloc(strlen(name));
				memcpy(client.name,name,strlen(name));
				client.type = static_cast<CLIENT_TYPE>(state);
			}else
			{
				printf("sorry there is no data with fd = [%d],we will create this\n",fd);
				result = -1;
			}
		}else
		{
			printf("There is no \"User\" key in file\n");
			result = -1;
		}
		cJSON_Delete(cjson);
		return result;
	}

	int create_file_for_state(const char* filename,char** content)
	{
		int ret = -1;
		FILE* fp;
		fp = fopen(filename, "wb+");
		cJSON* cjson = cJSON_CreateObject();
		cJSON* User = cJSON_CreateObject();
		cJSON_AddItemToObject(cjson,"User",User);
		*content = (char*)malloc(strlen(cJSON_Print(cjson)));
		memcpy(*content,cJSON_Print(cjson),strlen(cJSON_Print(cjson)));
		fseek(fp,0,SEEK_SET);
		ret = fwrite(*content,1,strlen(*content),fp);
		cJSON_Delete(cjson);
		fclose(fp);
		return ret;
	}

	int get_file_all(const char* filename, char** content)
	{
		FILE* fp;
		char txt[1000];
		int filesize;
		fp = fopen(filename, "r");
		ERROR_FUNC_PRINT(fp == NULL, "fopen");
		fseek(fp, 0, SEEK_END);
		filesize = ftell(fp);	
		*content = (char*)malloc(filesize);
		*content[0] = 0;
		fseek(fp, 0, SEEK_SET);
		while ((fgets(txt, 1000, fp) != NULL))
		{
			strcat(*content, txt);
		}
		fclose(fp);
		return 0;
	}

	int save_data_as_json(char** str, const ClientData& client)
	{
		cJSON* cjson = cJSON_Parse(*str);
		if (cjson == NULL)
		{
			printf("parse json error...");
			return -1;
		}
		cJSON* newJson = cJSON_CreateObject();
		cJSON_AddStringToObject(newJson, "ClientName", client.name);
		cJSON_AddNumberToObject(newJson, "ClientState", static_cast<int>(client.type));
		cJSON* usrJson = cJSON_GetObjectItem(cjson, "User");
		cJSON_AddItemToObject(usrJson, client.name, newJson);
		char* result_buf;
		size_t length = strlen(cJSON_Print(cjson));
		result_buf = (char*)malloc(length);
		memcpy(result_buf,cJSON_Print(cjson),length);
		*str = result_buf;
		cJSON_Delete(cjson);
		return 0;
	}

	int save_data_in_file(const char* filename, char* content)
	{
		FILE* fp;
		int ret = -1;
		fp = fopen(filename, "w+");
		ERROR_FUNC_PRINT(fp == NULL, "fopen");
		fseek(fp, 0, SEEK_SET);
		ret = fwrite(content, 1, strlen(content), fp);
		ERROR_FUNC_PRINT(ret < 0, "fopen");
		fclose(fp);
		return 0;
	}

	int to_up_word(char* content)
	{
		if(content == NULL)
			return -1;
		while(*content)
		{
			if(*content >= 'a' && *content <= 'z')
				(*content) -= 32;
			content++;
		}
		return 0;
	}

	int add_sig(int sig,void(*func)(int))
	{
		struct sigaction sa;
		memset(&sa,'\0',sizeof(sa));
		sa.sa_handler = func;
		sa.sa_flags = SA_RESTART;
		sigfillset(&sa.sa_mask);
		int ret = sigaction(sig,&sa,NULL);  //为信号添加信号处理函数
		if(ret < 0) perror("sigaction");
		return ret;
	}
};
